package cn.cloudtogo.common;

import cn.cloudtogo.common.model.ExternalDatasourceModel;
import cn.cloudtogo.common.types.ConnectString;
import cn.cloudtogo.common.types.Credential;
import cn.cloudtogo.common.types.DatasourceCreateObject;
import cn.cloudtogo.common.types.Endpoint;
import cn.cloudtogo.common.util.JdbcConnectionHelper;
import cn.cloudtogo.common.util.MongoConnectionHelper;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * @author yaolianhua789@gmail.com
 **/
public interface DatasourceCreateService {

    default String create(DatasourceCreateObject createObject) {
        Assert.notNull(createObject, () -> "datasourceCreateObject is null");

        String schema = createObject.getSchema();
        Assert.argument(schema != null && !schema.isEmpty(), () -> "schema is null");

        String id;
        if (StringUtils.hasText(createObject.getUrl())) {
            id = urlCreate(createObject);
        } else {
            Credential credential = createObject.getCredential();
            Endpoint endpoint = createObject.getEndpoint();
            Assert.notNull(credential, () -> "userInfo is null");
            Assert.notNull(endpoint, () -> "serverInfo is null");
            Assert.argument(StringUtils.hasText(credential.getUser()), () -> "user is null");
            Assert.argument(StringUtils.hasText(credential.getPassword()), () -> "password is null");
            Assert.argument(StringUtils.hasText(endpoint.getHost()), () -> "host is null");
            Assert.argument(endpoint.getPort() != null, () -> "port is null");
            id = basicCreate(createObject);
        }

        process(id);
        return id;
    }

    void process(String uuid);

    default void connectValidation(DatasourceCreateObject createObject) {

        ConnectString connectString = createObject.getConnectString();
        String url = createObject.obtainConnectUrl();
        boolean validConnection;
        switch (createObject.getType()) {
            case Mysql:
                if (StringUtils.hasText(createObject.getUrl())) {
                    if (!Objects.equals(connectString.getSchema(), createObject.getSchema())) {
                        throw new GendbException(String.format("parameter schema is [%s], but got schema is [%s] from url", createObject.getSchema(), connectString.getSchema()));
                    }
                }
                validConnection = JdbcConnectionHelper.isValidConnection(connectString);
                break;
            case Mongo:
                validConnection = MongoConnectionHelper.isValidConnection(connectString);
                break;
            default:
                throw new GendbException("Unsupported type [" + createObject.getType() + "]");

        }

        if (!validConnection) {
            throw new GendbException("中间件连接异常[" + url + "]");
        }
    }

    default String urlCreate(DatasourceCreateObject createObject) {
        connectValidation(createObject);

        ExternalDatasourceModel datasourceModel = modelSaved(createObject);

        return refreshTemplate(datasourceModel, createObject);
    }

    default String basicCreate(DatasourceCreateObject createObject) {
        connectValidation(createObject);

        ExternalDatasourceModel datasourceModel = modelSaved(createObject);

        return refreshTemplate(datasourceModel, createObject);
    }

    String refreshTemplate(ExternalDatasourceModel model, DatasourceCreateObject createObject);

    ExternalDatasourceModel modelSaved(DatasourceCreateObject createObject);

}
